package validjson;


import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class ObjectValidator implements Validator {
    private final Schema schemaMap;
    private final ValidatorFactory validatorFactory;
    private final List<String> mandatoryPropertyNames;
    private final Schema schemaPropertiesMap;

    public ObjectValidator(Schema schemaMap, ValidatorFactory validatorFactory) throws IOException {
        this.schemaMap = schemaMap;
        this.validatorFactory = validatorFactory;
        this.schemaPropertiesMap = schemaMap.getSubSchema("properties");
        this.mandatoryPropertyNames = schemaPropertiesMap == null ? new ArrayList<String>() : schemaPropertiesMap.getMandatoryPropertyNames();
    }

    public void validate(Object jsonToValidate) throws ValidationException {
        if (!(jsonToValidate instanceof Map)) {
            throw new ValidationException(String.format("Validator expected a value of type '%s' but got %s", "Map", jsonToValidate == null ? null : jsonToValidate.getClass()));
        }

        Map<String, Object> jsonValueMap = (Map<String, Object>) jsonToValidate;

        if (!jsonValueMap.keySet().containsAll(mandatoryPropertyNames)) {
            final List<String> missingProperties = new ArrayList<String>(mandatoryPropertyNames);
            missingProperties.removeAll(jsonValueMap.keySet());
            throw new ValidationException("Missing mandatory properties " + missingProperties);
        }

        for (String jsonValuePropertyName : jsonValueMap.keySet()) {
            try {
                Schema schemaPropertyMap = schemaPropertiesMap != null && schemaPropertiesMap.containsKey(jsonValuePropertyName) ? schemaPropertiesMap.getSubSchema(jsonValuePropertyName) : schemaMap.getSubSchema("additionalProperties");
                validatorFactory.createValidator(schemaPropertyMap, jsonValueMap.get(jsonValuePropertyName)).validate(jsonValueMap.get(jsonValuePropertyName));
            } catch (IOException e) {
                throw new ValidationException("Cannot read sub-schema", e);
            }
        }
    }

}
